#ifndef _AS_CONNECTOR_H_
#define _AS_CONNECTOR_H_

#include "net_include.h"
#include "net_addr.h"
#include "as_session.h"
#include <array>

#ifdef _WIN32
#include <minwinbase.h>
#include <MSWSock.h>
#endif

namespace as
{
namespace inet
{
class AS_DLL AsConnector
{
public:
    AsConnector();
    ~AsConnector();

public:
    AsConnector* set_workthread_num(int num = 1);

    AsConnector* start(NetAddr &addr);
    AsConnector* start(std::string_view ip);
    AsConnector* start(std::string_view host, int port);

    AsConnector* async_connect(std::string_view host, int port);
    AsConnector* reconnect();

    void register_sys_fun();
    void create_io_and_post_event();
    void stop();

    AsConnector* set_new_conn_cb(new_conn_cb cb)
    {
        m_new_con_cb = std::move(cb);
        return this;
    }

    AsConnector* set_recv_cb(recv_cb cb)
    {
       m_recv_cb = std::move(cb);
       return this;
    }

    AsConnector* set_write_cb(write_cb cb)
    {
        m_write_cb = std::move(cb);
        return this;
    }

    AsConnector* set_close_cb(close_cb cb)
    {
        m_close_cb = std::move(cb);
        return this;
    }

    bool is_connect()
    {
        return m_state == io_state::RUNNING;
    }

public:
    bool post_connect(IOContext *io);
    bool post_recv(IOContext *io);

    int DoConnect(IOContext *io);
    int DoRecv(IOContext *io, int byteNum);
    int DoWrite(IOContext *io, int byteNum);
    int DoClose(IOContext *io);

    void work_run();
    void run();

    static void signal_fun(int sig);
    static void RegSignal(int sig, const std::function<void()> cb_fun);
private:
    io_state m_state;

    NetAddr m_addr;

    //work thread
    std::vector<std::thread> m_workThreads;
    int m_workThreadNum = 1;

    std::array<IOContext, SVC_MAX_EVENT_NUM> m_events = {};

#ifdef _WIN32
    HANDLE m_ioPort;

    // load dll function
    static LPFN_CONNECTEX m_connect_fun;
#else
    int m_ioPort;
#endif
    std::shared_ptr<as::inet::AsSession> m_connectSocket;

    //function
    new_conn_cb m_new_con_cb;
    recv_cb m_recv_cb;
    write_cb m_write_cb;
    close_cb m_close_cb;

    static std::map<int, std::function<void()> > m_signal_map;
};


}
}

#endif